Skip to content

Conversation

@BoxyUwU
Copy link
Member

@BoxyUwU BoxyUwU commented Oct 10, 2025

"remove normalize call"

Fixes #132765 in theory breaking as we might now treat some previously-ambig hr aliases as rigid when we shouldn't. we may want to explicitly normalize the coercion target in fcx.coerce like the new solver does

"leak check and lub for closure<->closure coerce-lubs"

Fixes rust-lang/trait-system-refactor-initiative#233

fn peculiar() -> impl Fn(u8) -> u8 {
    return |x| x + 1
}

the |x| x + 1 expr has a type of Closure(?31t) which we wind up inferring the RPIT to. The CoerceMany ret_coercion for the whole peculiar typeck has an expected type of RPIT (unnormalized). When we type check the return |x| x + 1 expr we go from the never type to Closure(?31t) which then participates in the ret_coercion giving us a coerce-lub(RPIT, Closure(?31t)).

Normalizing RPIT gives us some Closure(?50t) where ?31t and ?50t have been unified with ?31t as the root var. resolve_vars_if_possible doesn't resolve infer vars to their roots so these wind up with different structural identities so the fast path doesn't apply and we fall back to coercing to a fn ptr. cc #147193 which also fixes this

New solver probably just gets more inference variables here because canonicalization + generally different approach to normalization of opaques. Idk :3

This technically allows more code to compile (see the test using TAIT in the commit). I don't think this can be observed on stable though.

In theory this could break existing code that relied on coercing a closure to itself resulting in a fnptr. I don't expect this to really happen in practice and this is an "obvious" bug fix.

misc additional leak checks :)

We now leak check in a lot more places:

  1. During subtyping occuring at coercion points. E.g. let a = b; will coerce b->a but if there's no coercion it just falls back to subtyping which is now leak checked.
  2. Coercing closure->fnptr now leak checks
  3. Coerce-lubbing fndef<->fndef now leak checks
  4. Coerce-lubbing fndef<->closure or closure<->fndef now leak checks

For 1 and 2 this should in theory only affect dead code as inside of livecode the borrow checker will wind up checking these constraints anyway. For 2 specifically it's worth noting that we already leak check fndef->fnptr and fnptr->fnptr coercions on stable.

3 allows more code to compile. Previously by not leak checking we could wind up thinking two fndefs were equal and so avoid coercing to a fnptr. Then borrowck would wind up emitting an error due to incompatible binders. See tests/ui/coercion/leak_check_fndef_lub.rs which failed to compile before this PR.

3 and 4 both stop some code from compiling in cases where the coerce-lub can only succeed due to lub arbitrarily returning the lhs for binders instead of a true "lub". See the order_dependence_x tests in tests/ui/coercion/leak_check_lub_to_fnptr.rs. Note that for fnptr<->fnptr coerce-lubs we already leak check on stable preventing equivalent code from compiling

similar to 1/2, both 3 and 4 should in theory also cause some code to stop compiling as we will be leak checking in dead code where borrowck is unable to emit errors.

TODO: I need to add some more tests here and properly link to them I think

"account for safe target features in fndef<->closure and fndef<->fndef coerce-lubs"

We previously did not take safe target features into account when creating the fn sig for fndefs during fndef<->closure or fndef<->fndef coerce-lubs. We now do allowing coerce-lub to produce a safe fn pointer when fndefs with safe target features are involved. This is consistent with existing (non lub) coercion logic for fndef->fnptr which allows coercing to a safe fn pointer.

r? ghost

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 10, 2025
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@BoxyUwU BoxyUwU force-pushed the coercion_cleanup branch 2 times, most recently from bce0933 to eb6434f Compare October 29, 2025 18:00
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@BoxyUwU BoxyUwU force-pushed the coercion_cleanup branch 2 times, most recently from 797201d to 3ecd1a8 Compare October 30, 2025 14:42
@rust-log-analyzer

This comment has been minimized.

@BoxyUwU BoxyUwU force-pushed the coercion_cleanup branch 2 times, most recently from 6179239 to 2958ef0 Compare October 30, 2025 15:19
@rust-log-analyzer

This comment has been minimized.

@rust-bors
Copy link

rust-bors bot commented Oct 31, 2025

☀️ Try build successful (CI)
Build commit: 08e75d5 (08e75d55141de8bb231c6b4a427aa0c28598a58a, parent: 23c7bad921fb7163de37ea680bed317deaa03fda)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (08e75d5): comparison URL.

Overall result: ❌ regressions - please read the text below

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please do so in sufficient writing along with @rustbot label: +perf-regression-triaged. If not, please fix the regressions and do another perf run. If its results are neutral or positive, the label will be automatically removed.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
0.8% [0.1%, 3.1%] 16
Regressions ❌
(secondary)
1.4% [0.1%, 5.2%] 33
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.8% [0.1%, 3.1%] 16

Max RSS (memory usage)

Results (primary 1.4%, secondary 1.4%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
3.6% [1.8%, 5.3%] 3
Regressions ❌
(secondary)
1.4% [1.4%, 1.4%] 1
Improvements ✅
(primary)
-1.9% [-2.1%, -1.6%] 2
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 1.4% [-2.1%, 5.3%] 5

Cycles

Results (primary 2.6%, secondary 3.8%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
2.6% [2.0%, 3.0%] 3
Regressions ❌
(secondary)
3.8% [2.7%, 5.9%] 11
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 2.6% [2.0%, 3.0%] 3

Binary size

Results (primary 0.3%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
0.4% [0.1%, 1.1%] 4
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-0.0% [-0.0%, -0.0%] 1
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.3% [-0.0%, 1.1%] 5

Bootstrap: 473.971s -> 475.243s (0.27%)
Artifact size: 390.89 MiB -> 390.88 MiB (-0.00%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Oct 31, 2025
@BoxyUwU
Copy link
Member Author

BoxyUwU commented Nov 1, 2025

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors bot added a commit that referenced this pull request Nov 1, 2025
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Nov 1, 2025
@rust-log-analyzer

This comment has been minimized.

@rust-bors
Copy link

rust-bors bot commented Nov 1, 2025

☀️ Try build successful (CI)
Build commit: 460970f (460970fa89d49bb599655087c5a59161582a581f, parent: 82ae0ee6487e93bd6c05167ccb2ef3485fdbc890)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (460970f): comparison URL.

Overall result: ❌ regressions - please read the text below

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please do so in sufficient writing along with @rustbot label: +perf-regression-triaged. If not, please fix the regressions and do another perf run. If its results are neutral or positive, the label will be automatically removed.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
0.9% [0.2%, 1.5%] 9
Regressions ❌
(secondary)
1.7% [0.2%, 4.9%] 23
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.9% [0.2%, 1.5%] 9

Max RSS (memory usage)

Results (primary -0.4%, secondary 1.8%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
2.7% [1.8%, 3.5%] 2
Regressions ❌
(secondary)
1.8% [1.5%, 2.1%] 2
Improvements ✅
(primary)
-1.9% [-2.6%, -1.1%] 4
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -0.4% [-2.6%, 3.5%] 6

Cycles

Results (primary 5.6%, secondary 2.4%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
5.6% [2.1%, 8.3%] 9
Regressions ❌
(secondary)
3.3% [2.4%, 4.8%] 11
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.5% [-2.6%, -2.5%] 2
All ❌✅ (primary) 5.6% [2.1%, 8.3%] 9

Binary size

Results (primary 0.1%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
0.1% [0.1%, 0.1%] 3
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-0.0% [-0.0%, -0.0%] 1
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.1% [-0.0%, 0.1%] 4

Bootstrap: 475.716s -> 473.379s (-0.49%)
Artifact size: 390.89 MiB -> 390.91 MiB (0.00%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Nov 1, 2025
@BoxyUwU
Copy link
Member Author

BoxyUwU commented Nov 1, 2025

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

rust-bors bot added a commit that referenced this pull request Nov 1, 2025
@rust-bors

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Nov 1, 2025
@rust-log-analyzer
Copy link
Collaborator

The job tidy failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
[TIMING:end] tool::ToolBuild { build_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu, tool: "tidy", path: "src/tools/tidy", mode: ToolBootstrap, source_type: InTree, extra_features: [], allow_features: "", cargo_args: [], artifact_kind: Binary } -- 11.569
[TIMING:end] tool::Tidy { compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu } -- 0.000
fmt check
Diff in /checkout/compiler/rustc_hir_typeck/src/coercion.rs:854:
                 let a = Ty::new_fn_ptr(self.tcx, a_sig);
 
                 let adjust = Adjust::Pointer(PointerCoercion::ReifyFnPointer);
-                let (a, opt_adjustment, adjust) = if a_sig.safety().is_safe() && b_hdr.safety.is_unsafe() {
-                    let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(a_sig);
-                    (unsafe_a, Some(Adjustment { kind: adjust, target: a }), Adjust::Pointer(PointerCoercion::UnsafeFnPointer))
-                } else {
-                    (a, None, adjust)
-                };
-                let InferOk { value, obligations: o2 } = self.unify_and(a, b, opt_adjustment, adjust)?;
+                let (a, opt_adjustment, adjust) =
+                    if a_sig.safety().is_safe() && b_hdr.safety.is_unsafe() {
+                        let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(a_sig);
+                        (
+                            unsafe_a,
+                            Some(Adjustment { kind: adjust, target: a }),
+                            Adjust::Pointer(PointerCoercion::UnsafeFnPointer),
+                        )
+                    } else {
+                        (a, None, adjust)
+                    };
+                let InferOk { value, obligations: o2 } =
+                    self.unify_and(a, b, opt_adjustment, adjust)?;
 
                 obligations.extend(o2);
                 Ok(InferOk { value, obligations })
Diff in /checkout/compiler/rustc_hir_typeck/src/coercion.rs:1213:
             // Allow coercing safe sigs to unsafe sigs
             let mut adjust_a_safety = false;
             let mut adjust_b_safety = false;
-            
+
             if a_sig.safety().is_safe() && b_sig.safety().is_unsafe() {
                 a_sig = self.tcx.safe_to_unsafe_sig(a_sig);
                 adjust_a_safety = true;
Diff in /checkout/compiler/rustc_hir_typeck/src/coercion.rs:1250:
             let adjustments = |adjust_kind, should_adjust_safety| {
                 let mut adjustments = Vec::with_capacity(2);
 
-                let unadjusted_fn_ptr = if should_adjust_safety {
-                    safe_fn_ptr
-                } else {
-                    fn_ptr
-                };
+                let unadjusted_fn_ptr = if should_adjust_safety { safe_fn_ptr } else { fn_ptr };
 
-                adjustments.push(
-                    Adjustment { kind: adjust_kind, target: unadjusted_fn_ptr }
-                );
+                adjustments.push(Adjustment { kind: adjust_kind, target: unadjusted_fn_ptr });
                 if should_adjust_safety {
-                    adjustments.push(
-                        Adjustment { kind: Adjust::Pointer(PointerCoercion::UnsafeFnPointer), target: fn_ptr}
-                    )
+                    adjustments.push(Adjustment {
+                        kind: Adjust::Pointer(PointerCoercion::UnsafeFnPointer),
+                        target: fn_ptr,
+                    })
                 }
 
                 adjustments
Diff in /checkout/compiler/rustc_hir_typeck/src/coercion.rs:1269:
             };
-            
+
             for expr in exprs.iter().map(|e| e.as_coercion_site()) {
-                self.apply_adjustments(
-                    expr,
-                    adjustments(prev_adjustment.clone(), adjust_a_safety),
-                );
+                self.apply_adjustments(expr, adjustments(prev_adjustment.clone(), adjust_a_safety));
             }
             self.apply_adjustments(new, adjustments(next_adjustment, adjust_b_safety));
             return Ok(fn_ptr);
Diff in /checkout/compiler/rustc_borrowck/src/type_check/mod.rs:1062:
 
             Rvalue::Cast(cast_kind, op, ty) => {
                 match *cast_kind {
-                    CastKind::PointerCoercion(
-                        PointerCoercion::ReifyFnPointer,
-                        coercion_source,
-                    ) => {
+                    CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, coercion_source) => {
                         let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
                         let src_ty = op.ty(self.body, tcx);
                         let mut src_sig = src_ty.fn_sig(tcx);
Diff in /checkout/compiler/rustc_middle/src/ty/context.rs:2854:
     /// that is, a `fn` sig that is equivalent in every way for being
     /// safe.
     pub fn unsafe_to_safe_sig(self, sig: PolyFnSig<'tcx>) -> PolyFnSig<'tcx> {
-        sig.map_bound(|sig| ty::FnSig{ safety: hir::Safety::Safe, ..sig  })
+        sig.map_bound(|sig| ty::FnSig { safety: hir::Safety::Safe, ..sig })
     }
 
     /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
fmt: checked 6519 files
Bootstrap failed while executing `test src/tools/tidy tidyselftest --extra-checks=py,cpp,js,spellcheck`

@rust-bors
Copy link

rust-bors bot commented Nov 1, 2025

☀️ Try build successful (CI)
Build commit: 29354ec (29354ecf91357b53f874f0d9038763f742c2dde3, parent: d85276b256a8ab18e03b6394b4f7a7b246176db7)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (29354ec): comparison URL.

Overall result: ❌✅ regressions and improvements - please read the text below

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please do so in sufficient writing along with @rustbot label: +perf-regression-triaged. If not, please fix the regressions and do another perf run. If its results are neutral or positive, the label will be automatically removed.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
0.9% [0.2%, 1.6%] 10
Regressions ❌
(secondary)
1.4% [0.1%, 4.7%] 30
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.2% [-0.2%, -0.2%] 1
All ❌✅ (primary) 0.9% [0.2%, 1.6%] 10

Max RSS (memory usage)

Results (primary 0.8%, secondary 0.7%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
4.4% [1.9%, 7.6%] 3
Regressions ❌
(secondary)
0.7% [0.7%, 0.7%] 1
Improvements ✅
(primary)
-1.8% [-2.8%, -0.9%] 4
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.8% [-2.8%, 7.6%] 7

Cycles

Results (secondary 3.2%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
3.2% [2.2%, 4.7%] 9
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Binary size

Results (primary 0.1%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
0.1% [0.1%, 0.2%] 3
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-0.0% [-0.0%, -0.0%] 1
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.1% [-0.0%, 0.2%] 4

Bootstrap: 476.797s -> 477.705s (0.19%)
Artifact size: 390.82 MiB -> 390.86 MiB (0.01%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Nov 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

perf-regression Performance regression. S-waiting-on-crater Status: Waiting on a crater run to be completed. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FulfillmentErrorCode::Project ICE for opaques [ICE]: index out of bounds

5 participants